package rm2;

import java.net.*;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.io.*;

import threads.BuyItem;
import threads.CheckInfo;
import threads.CheckItemList;
import threads.ItemAddition;
import threads.ItemDeduction;

import exception.BuyToManyException;
import exception.CustomerNotExistsException;
import exception.ItemNotExistsException;

class UDPServer implements Runnable
{
	Thread thread;
	DatagramSocket socket;
	int port ;
	DRSserverinit server;

	UDPServer(DRSserverinit server)
	{
		this.server=server;
		port=server.udp_port;
		thread = new Thread(this);
		thread.start();
	}

	public void run()
	{
		try
		{
			byte[] buffer = new byte[512];
			String message = "";
			
			try
			{
				socket = new DatagramSocket(port);
				System.out.println(server.server + " Server is listening at " + server.udp_port + ".");
				
				while (true)
				{
					try
					{						
						// Receive request from client
						DatagramPacket packet = new DatagramPacket(buffer,	buffer.length);
						socket.receive(packet);
						InetAddress client = packet.getAddress();
						// int client_port = packet.getPort();
						message = new String(packet.getData()).trim(); 
						System.out.println("Received: " + message + " from " + client.getHostAddress());										
						
						// Process request of other servers
						String reply = processServerRequest(message);
						
						// Reply to the requestor//						
						byte send_buffer[] = reply.getBytes();
						packet = new DatagramPacket(send_buffer, send_buffer.length, client, packet.getPort());
				        socket.send(packet);						

					} catch (UnknownHostException ue)
					{
						System.out.println(ue.getMessage());
						ue.printStackTrace();
					}
				}
			} catch (java.net.BindException b)
			{
				System.out.println(b.getMessage());
				b.printStackTrace();
			}
		} catch (IOException e)
		{
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
	}
	
	String processServerRequest(String message)
	{
		String reply = "";
		StringTokenizer st = new StringTokenizer(message, "~");
//		while(st.hasMoreTokens()){
//			System.out.println(st.nextToken());
//		}
		String option = st.nextToken();
		if(option.equalsIgnoreCase("checkstockU"))
		{
			reply = /*server.server + " " + */Integer.toString(checkStock(st.nextToken().trim(),false));
			System.out.println("final reply for U: "+reply);
		}
		else if(option.equalsIgnoreCase("checkstock"))
		{
			reply = /*server.server + " " + */Integer.toString(checkStock(st.nextToken().trim(),true));
			System.out.println("final reply: "+reply);
		}
		else if(option.equalsIgnoreCase("buy"))
		{
			String customer_id = st.nextToken();
			String item_id = st.nextToken();
			int quantity = Integer.parseInt(st.nextToken());			
			
			reply = /*"buy " + customer_id + " " + item_id + " " + */buy(customer_id, item_id, quantity);	
			System.out.println("final reply: "+reply);
		}
		else if(option.equalsIgnoreCase("return"))
		{
			String customer_id = st.nextToken();
			String item_id = st.nextToken();
			int quantity = Integer.parseInt(st.nextToken());			
			
			reply = /*"return " + customer_id + " " + item_id + " " + */Return(customer_id, item_id, quantity);			
		}
		else if(option.equalsIgnoreCase("exchange"))
		{
			String customer_id = st.nextToken();
			String bought_item_id = st.nextToken();
			int bought_quantity = Integer.parseInt(st.nextToken());
			String desired_item_id = st.nextToken();
			int desired_quantity = Integer.parseInt(st.nextToken());
			
			reply = /*"return " + customer_id + " " + bought_item_id + " " + desired_item_id + " " + */Exchange(customer_id, bought_item_id, bought_quantity, desired_item_id, desired_quantity);			
		}
		
		System.out.println("test: " + reply);
		return reply;
	}
	
	int checkStock(String item_id, boolean udpCheck)
	{	
		int total=0;
		CheckItemList checklist = new CheckItemList(item_id,server);
		//reply = checklist.start();	
		String reply = checklist.checkItem(udpCheck);
		System.out.println("total checkstock = "+ reply);
		return Integer.parseInt(reply);
	}
	
	String buy(String customer, String item, int number)
	{	
		String message = "0";
		try
		{
			
			if(server.slist.get(item) == null)
				throw new ItemNotExistsException(customer + " --> Buying" + ": " + "Item: " + item + " does not exist.");
			
			
			if(number > server.slist.get(item).getCapacity())
				message = "0";
				//throw new BuyToManyException(customer  +" --> Buying" + ": " + item+" Either out of stock or too many items .");
		
			//File file = new File("input\\CustomerFile" + File.separator + customer);
			File file = new File(server.input_folder_path  + File.separator + "CustomerFile" + File.separator + customer);
			
			if (file.exists())
			{			
				
					ItemAddition ca = new ItemAddition(server);					
					
					synchronized (server.slist.get(item)) 
					{
						ca.addItem(customer, item, number);
						message = String.valueOf(number);
					}				
					
					
					System.out.println(customer + " bought " + number + " unit(s) of " + item);

			}
			else
				System.out.println("customer doesnt exist");
				message = Integer.toString(0);
				//throw new CustomerNotExistsException(customer  +" --> " + ": " + " Customer does not exist.");
			//End of FileExist
		}
		catch (Exception e) 
		{
			System.out.println(e.getMessage());
			e.printStackTrace();
		}

		return message;
	}
	
	public String Return(String customer, String item, int number)
	{		
		String message = "0";
		try
		{
			
			if(server.slist.get(item) == null)
				throw new ItemNotExistsException(customer + " --> Returning" + ": " + "Item: " + item + " does not exist.");
			
		
			File file = new File(server.input_folder_path + File.separator + "CustomerFile" + File.separator + customer);

			
			if (file.exists())
			{			
				
					ItemDeduction ca = new ItemDeduction(server);
					//System.out.println("test3");
					ca.removeItem(customer, item, number);
					System.out.println(customer  +" returned " + number + " unit(s) of " + item);
					message = "1";
			}
			else
				throw new CustomerNotExistsException(customer  +" --> Return" + ": " + " Customer does not exist.");
			//End of FileExist
		}
		catch (Exception e) 
		{
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
		return message;
		
	}	
	
	public String Exchange(String customer, String bought_item, int bought_number, String  desired_item, int desired_number)
	{		
		String message = "0";
		String buyMessage = "0";
		String returnMessage = "0";
		try
		{
			File file = new File(server.input_folder_path + File.separator + "CustomerFile" + File.separator + customer);
			
			CheckInfo ci = new CheckInfo(server);
			if (file.exists())
			{			
				if(server.slist.get(bought_item) == null)
					throw new ItemNotExistsException(customer + ": " + "Item: " + bought_item + " does not exist.");
					
					if(ci.CheckBoughtItem(customer, bought_item, bought_number))
					{
						ItemDeduction ca = new ItemDeduction(server);
						//System.out.println("test3");
						synchronized (server.slist) 
						{
							ca.removeItem(customer, bought_item, bought_number);
							System.out.println(customer  +" returned " + bought_number + " unit(s) of " + bought_item);
							returnMessage = "1";
						}
					}else{
						message="2";
					}
					
			}
			else{
				message="2";
				throw new CustomerNotExistsException(customer  +" --> Return" + ": " + " Customer does not exist.");
				
			}
			
			File file1 = new File(server.input_folder_path  + File.separator + "ItemList");
			
			if (file1.exists())
			{			
				if(server.slist.get(desired_item) == null)
					throw new ItemNotExistsException(customer + ": " + "Item: " + desired_item + " does not exist.");
					
					if(ci.CheckDesiredItem(customer, desired_item, desired_number))
					{
						ItemAddition ca = new ItemAddition(server);					
						
						synchronized (server.slist.get(desired_item)) 
						{
							ca.addItem(customer, desired_item, desired_number);
							buyMessage = "1";
						}				
						
						
						System.out.println(customer + " bought " + desired_number + " unit(s) of " + desired_item);
						
					}else{
						message = "0";
					}
			}
			else{
				message = "0";
				throw new CustomerNotExistsException(customer  +" --> Return" + ": " + " Customer does not exist.");
			}
			//End of FileExist
		}
		catch (Exception e) 
		{
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
		if(buyMessage=="1"&&returnMessage=="1"){
			message="1";
		}
		return message;
		
	}	

//public static void main(String[] args) {
//	DRSserverinit si = new DRSserverinit("DRSSInput/Montreal");	
//	UDPServer s = new UDPServer(si);
//	
//	DRSserverinit si1 = new DRSserverinit("DRSSInput/Toronto");	
//	UDPServer s1 = new UDPServer(si1);
//	
//	DRSserverinit si2 = new DRSserverinit("DRSSInput/Vancouver");	
//	UDPServer s2 = new UDPServer(si2);
//	
//	s.checkStock("1111",true);
//}
}